package com.hospital.hospitalsystem.modules.user.biz;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.hospital.hospitalsystem.base.PageData;
import com.hospital.hospitalsystem.modules.login.dao.entity.HospitalMessageEntity;
import com.hospital.hospitalsystem.modules.login.dao.entity.UserMessageEntity;
import com.hospital.hospitalsystem.modules.login.dto.EmailEntityExt;
import com.hospital.hospitalsystem.modules.login.service.HospitalMessageService;
import com.hospital.hospitalsystem.modules.login.service.UserMessageService;
import com.hospital.hospitalsystem.modules.medicine.biz.HospitalMedicalBiz;
import com.hospital.hospitalsystem.modules.medicine.dao.entity.HospitalMedicalEntity;
import com.hospital.hospitalsystem.modules.medicine.dao.entity.HospitalMedicalHistoryEntity;
import com.hospital.hospitalsystem.modules.medicine.service.HospitalMedicalHistoryService;
import com.hospital.hospitalsystem.modules.medicine.service.HospitalMedicalService;
import com.hospital.hospitalsystem.modules.user.dao.entity.AddressEntity;
import com.hospital.hospitalsystem.modules.user.dao.entity.ExpressCompanyEntity;
import com.hospital.hospitalsystem.modules.user.dao.entity.OrderEntity;
import com.hospital.hospitalsystem.modules.user.dto.*;
import com.hospital.hospitalsystem.modules.user.service.AddressService;
import com.hospital.hospitalsystem.modules.user.service.ExpressCompanyService;
import com.hospital.hospitalsystem.modules.user.service.OrderService;
import com.hospital.hospitalsystem.utils.KdApiSearch;
import com.hospital.hospitalsystem.utils.SendEmailUtils;
import lombok.Data;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.simpleframework.xml.Order;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author qiancheng@cqxyy.net
 * @date 2023/4/19
 */
@Data
@Service
public class OrderBiz {

    @Autowired
    private OrderService orderService;

    @Autowired
    private HospitalMessageService hospitalMessageService;

    @Autowired
    private HospitalMedicalService hospitalMedicalService;

    @Autowired
    private HospitalMedicalHistoryService hospitalMedicalHistoryService;

    @Autowired
    private UserMessageService userMessageService;

    @Autowired
    private KdApiSearch kdApiSearch;

    @Autowired
    private ExpressCompanyService expressCompanyService;

    @Autowired
    private AddressService addressService;

    @Autowired
    private HospitalMedicalBiz hospitalMedicalBiz;

    @Autowired
    private SendEmailUtils sendEmailUtils;

    /**
     * 用户下订单
     * @param req
     */
    public void buyMedical(BuyOrderReq req) {
        Example exampleAddress = new Example(AddressEntity.class);
        Example.Criteria criteriaAddress = exampleAddress.createCriteria();
        criteriaAddress.andEqualTo("userUuid",req.getUserUuid());
        criteriaAddress.andEqualTo("uuid",req.getAddressUuid());
        AddressEntity addressEntity = addressService.selectByExample(exampleAddress).get(0);
        Map<String,List<HospitalMedicalEntity>> hospitalMedicalEntities = hospitalMedicalService.buyMedical(req).stream().
                collect(Collectors.groupingBy(s->s.getHospitalUuid()));
        if (CollectionUtils.isNotEmpty(req.getList())) {
            Map<String,List<BuyOrderExt>> hospitalOrder = req.getList().stream().collect(Collectors.groupingBy(s->s.getHospitalUuid()));
            hospitalOrder.forEach((key,value) -> {
                Map<String,HospitalMedicalEntity> medicals = hospitalMedicalEntities.get(key).stream().
                        collect(Collectors.toMap(s->s.getMedicalUuid(),s->s));
                OrderEntity orderEntity = new OrderEntity();
                orderEntity.setOrderUuid(UUID.randomUUID().toString());
                orderEntity.setHospitalUuid(key);
                orderEntity.setUserUuid(req.getUserUuid());
                orderEntity.setAddress(addressEntity.getArea() + " " + addressEntity.getDetail() + " (" + addressEntity.getName() + " 收) " +
                        addressEntity.getTel());
                orderEntity.setStatus(1);
                BigDecimal price = new BigDecimal(0);
                List<OrderContentExt> tmp = new ArrayList<>();
                for (int i = 0; i < value.size(); i++) {
                    HospitalMedicalEntity hospitalMedicalEntity = new HospitalMedicalEntity();
                    hospitalMedicalEntity.setReserveCount(medicals.get(value.get(i).getMedicalUuid()).getReserveCount() - value.get(i).getCount());
                    Example example = new Example(HospitalMedicalEntity.class);
                    Example.Criteria criteria = example.createCriteria();
                    criteria.andEqualTo("hospitalUuid",key);
                    criteria.andEqualTo("medicalUuid",value.get(i).getMedicalUuid());
                    hospitalMedicalService.updateByExampleSelective(hospitalMedicalEntity,example);
                    price = price.add(value.get(i).getPrice().multiply(new BigDecimal(value.get(i).getCount())));
                    OrderContentExt orderContentExt = new OrderContentExt();
                    orderContentExt.setMedicalUuid(value.get(i).getMedicalUuid());
                    orderContentExt.setCount(value.get(i).getCount());
                    tmp.add(orderContentExt);
                }
                orderEntity.setPrice(price);
                orderEntity.setOrderContent(JSONObject.toJSONString(tmp));
                orderService.insertSelective(orderEntity);
            });
        }
    }

    /**
     * 查找订单
     * @param req
     * @return
     */
    public PageData<SearchOrderRsp> medicalList(SearchOrderListReq req) {
        com.github.pagehelper.Page<SearchOrderRsp> page = PageHelper.startPage(
                req.getCurrentPage(), req.getPageSize()
        );
        Example example = new Example(OrderEntity.class);
        Example.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotBlank(req.getUserUuid())) {
            criteria.andEqualTo("userUuid",req.getUserUuid());
        }
        if (CollectionUtils.isNotEmpty(req.getStatus())) {
            criteria.andIn("status",req.getStatus());
        }
        if (StringUtils.isNotBlank(req.getHospitalUuid())) {
            criteria.andEqualTo("hospitalUuid",req.getHospitalUuid());
        }
        example.orderBy("createTime").desc();
        List<SearchOrderRsp> list = orderService.selectByExample(example).stream().map(item -> {
            SearchOrderRsp searchOrderRsp = new SearchOrderRsp();
            BeanUtils.copyProperties(item,searchOrderRsp);
            searchOrderRsp.setOrderContent((List<OrderContentExt>)JSONObject.parse(item.getOrderContent()));
            return searchOrderRsp;
        }).collect(Collectors.toList());
        List<String> userUuids = list.stream().map(s->s.getUserUuid()).collect(Collectors.toList());
        List<String> hospitalUuids = list.stream().map(s->s.getHospitalUuid()).collect(Collectors.toList());
        Example exampleHospital = new Example(HospitalMessageEntity.class);
        Example.Criteria criteriaHospital = exampleHospital.createCriteria();
        if (CollectionUtils.isNotEmpty(hospitalUuids)) {
            criteriaHospital.andIn("uuid",hospitalUuids);
        }
        Example exampleUser = new Example(UserMessageEntity.class);
        Example.Criteria criteriaUser = exampleUser.createCriteria();
        if (CollectionUtils.isNotEmpty(userUuids)) {
            criteriaUser.andIn("uuid",userUuids);
        }
        Map<String,UserMessageEntity> tmpUser = userMessageService.selectByExample(exampleUser).stream().
                collect(Collectors.toMap(s->s.getUuid(),s->s));
        Map<String,HospitalMessageEntity> tmp = hospitalMessageService.selectByExample(exampleHospital).stream()
                .collect(Collectors.toMap(s->s.getUuid(),s->s));
        list.forEach(item -> {
            item.setUserName(tmpUser.get(item.getUserUuid()).getName());
            item.setHospitalName(tmp.get(item.getHospitalUuid()).getName());
        });
        int longs = ((Number) page.getTotal()).intValue();
        PageData<SearchOrderRsp> pageData = PageData.of(list,page.getPageNum(),page.getPageSize(),longs);
        return pageData;
    }

    /**
     * 删除订单
     * @param req
     */
    public void medicalDelete(OrderMedicalReq req) {
        Example exampleOrder = new Example(OrderEntity.class);
        Example.Criteria criteriaOrder = exampleOrder.createCriteria();
        criteriaOrder.andEqualTo("orderUuid",req.getOrderUuid());
        criteriaOrder.andEqualTo("userUuid",req.getUserUuid());

        OrderEntity orderEntity = orderService.selectByExample(exampleOrder).get(0);
        List<MedicalsExt> list = JSONObject.parseArray(orderEntity.getOrderContent(),MedicalsExt.class);
        List<String> medicalUuids = list.stream().map(s->s.getMedicalUuid()).collect(Collectors.toList());
        Example example = new Example(HospitalMedicalEntity.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("hospitalUuid",orderEntity.getHospitalUuid());
        criteria.andIn("medicalUuid",medicalUuids);
        Map<String,HospitalMedicalEntity> map = hospitalMedicalService.selectByExample(example).stream().collect(Collectors.toMap(s->s.getMedicalUuid(),s->s));
        list.forEach(item -> {
            Example example1 = new Example(HospitalMedicalEntity.class);
            Example.Criteria criteria1 = example1.createCriteria();
            criteria1.andEqualTo("hospitalUuid",orderEntity.getHospitalUuid());
            criteria1.andEqualTo("medicalUuid",item.getMedicalUuid());
            HospitalMedicalEntity hospitalMedicalEntity = map.get(item.getMedicalUuid());
            HospitalMedicalEntity change = new HospitalMedicalEntity();
            change.setReserveCount(hospitalMedicalEntity.getReserveCount() + item.getCount());
            hospitalMedicalService.updateByExampleSelective(change,example1);
        });
        orderService.deleteByExample(exampleOrder);
    }

    /**
     * 填写快递单号并出库
     * @param req
     */
    public void medicalSend(OrderMedicalReq req) {
        OrderEntity orderEntity = new OrderEntity();
        orderEntity.setStatus(2);
        orderEntity.setDeliveryTime(new Date());
        orderEntity.setExpressId(req.getExpressId());
        orderEntity.setExpressUuid(req.getExpressUuid());
        Example exampleOrder = new Example(OrderEntity.class);
        Example.Criteria criteriaOrder = exampleOrder.createCriteria();
        criteriaOrder.andEqualTo("orderUuid",req.getOrderUuid());
        criteriaOrder.andEqualTo("hospitalUuid",req.getHospitalUuid());
        OrderEntity tmp = orderService.selectByExample(exampleOrder).get(0);
        List<OrderContentExt> list = JSONObject.parseArray(tmp.getOrderContent(),OrderContentExt.class);
        List<String> medicalUuids = list.stream().map(s->s.getMedicalUuid()).collect(Collectors.toList());
        Example exampleMedical = new Example(HospitalMedicalEntity.class);
        Example.Criteria criteriaMedical = exampleMedical.createCriteria();
        criteriaMedical.andEqualTo("hospitalUuid",req.getHospitalUuid());
        criteriaMedical.andIn("medicalUuid",medicalUuids);
        Map<String,HospitalMedicalEntity> map = hospitalMedicalService.selectByExample(exampleMedical).stream().
                collect(Collectors.toMap(s->s.getMedicalUuid(),s->s));
        list.forEach(item -> {
            HospitalMedicalHistoryEntity hospitalMedicalHistoryEntity = new HospitalMedicalHistoryEntity();
            hospitalMedicalHistoryEntity.setHospitalUuid(req.getHospitalUuid());
            hospitalMedicalHistoryEntity.setOperateUuid(req.getUserUuid());
            hospitalMedicalHistoryEntity.setType(4);
            hospitalMedicalHistoryEntity.setMsg("出库药品:" + map.get(item.getMedicalUuid()).getName() + " 数量:" +
                    item.getCount() + hospitalMedicalBiz.returnUnit(map.get(item.getMedicalUuid()).getUnit()) + " " + "类型:用户购买");
            hospitalMedicalHistoryService.insertSelective(hospitalMedicalHistoryEntity);

            HospitalMedicalEntity hospitalMedicalEntity = new HospitalMedicalEntity();
            hospitalMedicalEntity.setCount(map.get(item.getMedicalUuid()).getCount() - item.getCount());
            Example exampleMedicals = new Example(HospitalMedicalEntity.class);
            Example.Criteria criteriaMedicals = exampleMedicals.createCriteria();
            criteriaMedicals.andEqualTo("hospitalUuid",req.getHospitalUuid());
            criteriaMedicals.andEqualTo("medicalUuid",item.getMedicalUuid());
            hospitalMedicalService.updateByExampleSelective(hospitalMedicalEntity,exampleMedicals);
        });
        orderService.updateByExampleSelective(orderEntity,exampleOrder);
    }

    /**
     * 根据订单uuid获取详细信息
     * @param req
     * @return
     */
    public OrderDetailRsp getDetail(OrderMedicalReq req) {
        Example example = new Example(OrderEntity.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("orderUuid",req.getOrderUuid());
        OrderEntity orderEntity = orderService.selectByExample(example).get(0);
        ExpressCompanyEntity expressCompanyEntity = new ExpressCompanyEntity();
        if (StringUtils.isNotBlank(orderEntity.getExpressUuid())) {
            Example exampleExpress = new Example(ExpressCompanyEntity.class);
            Example.Criteria criteriaExpress = exampleExpress.createCriteria();
            criteriaExpress.andEqualTo("expressUuid",orderEntity.getExpressUuid());
            expressCompanyEntity = expressCompanyService.selectByExample(exampleExpress).get(0);
        }
        OrderEntity orderEntitys = new OrderEntity();
        if (orderEntity.getStatus() == 2) {
            try {
                String logistic = kdApiSearch.orderOnlineByJson(expressCompanyEntity.getCode(),orderEntity.getExpressId()).toJSONString();
                orderEntitys = new OrderEntity();
                orderEntitys.setLogistics(logistic);
                orderService.updateByExampleSelective(orderEntitys,example);
            }catch (Exception e){
                throw new RuntimeException("查询快递信息失败");
            }
        }
//        Example exampleAddress = new Example(AddressEntity.class);
//        Example.Criteria criteriaAddress = exampleAddress.createCriteria();
//
//        criteriaAddress.andEqualTo("userUuid",orderEntity.getUserUuid());
//        criteriaAddress.andEqualTo("uuid",orderEntity.getAddressUuid());
//        AddressEntity addressEntity = addressService.selectByExample(exampleAddress).get(0);
        orderEntity = orderService.selectByExample(example).get(0);
        OrderDetailRsp orderDetailRsp = new OrderDetailRsp();
        orderDetailRsp.setAddress(orderEntity.getAddress());
//        orderDetailRsp.setDetail(addressEntity.getDetail());
//        orderDetailRsp.setArea(addressEntity.getArea());
        orderDetailRsp.setExpressCompany(expressCompanyEntity.getName());
        orderDetailRsp.setDeliveryTime(orderEntity.getDeliveryTime());
        orderDetailRsp.setLogistics(orderEntity.getLogistics());
        orderDetailRsp.setExpressId(orderEntity.getExpressId());
        return orderDetailRsp;
    }

    /**
     * 结算前查看商品列表
     * @param req
     * @return
     */
    public List<BeforePlaceOrderRsp> beforePlaceOrder(BeforePlaceOrderReq req) {
        List<BeforePlaceOrderRsp> result = orderService.beforePlaceOrder(req);
        result.forEach(s -> {
            req.getList().forEach(s1 -> {
                if (s1.getHospitalUuid().equals(s.getHospitalUuid()) && s1.getMedicalUuid().equals(s.getMedicalUuid())) {
                    s.setCount(s1.getCount());
                    return;
                }
            });
        });
        return result;
    }

    /**
     * 获取快递公司
     * @return
     */
    public List<ExpressCompanyRsp> expressCompany() {
        List<ExpressCompanyRsp> list = expressCompanyService.selectAll().stream().map(item -> {
            ExpressCompanyRsp expressCompanyRsp = new ExpressCompanyRsp();
            expressCompanyRsp.setExpressUuid(item.getExpressUuid());
            expressCompanyRsp.setName(item.getName());
            return expressCompanyRsp;
        }).collect(Collectors.toList());
        return list;
    }

    /**
     * 确认收货
     * @param req
     */
    public void medicalSuccess(OrderMedicalReq req) {
        Example example = new Example(OrderEntity.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("userUuid",req.getUserUuid());
        criteria.andEqualTo("orderUuid",req.getOrderUuid());
        OrderEntity orderEntity = new OrderEntity();
        orderEntity.setStatus(3);
        orderService.updateByExampleSelective(orderEntity,example);
    }

    /**
     * 抓药师根据用户uuid和订单uuid撤销订单
     * @param req
     */
    public void cancel(OrderCancelReq req) {
        EmailEntityExt emailEntityExt = new EmailEntityExt();
        Example exampleUser = new Example(UserMessageEntity.class);
        Example.Criteria criteriaUser = exampleUser.createCriteria();
        criteriaUser.andEqualTo("uuid",req.getUserUuid());
        UserMessageEntity userMessageEntity = userMessageService.selectByExample(exampleUser).get(0);
        emailEntityExt.setEmail(userMessageEntity.getEmail());
        Example exampleHospital = new Example(HospitalMessageEntity.class);
        Example.Criteria criteriaHospital = exampleHospital.createCriteria();
        criteriaHospital.andEqualTo("uuid",req.getHospitalUuid());
        HospitalMessageEntity hospitalMessageEntity = hospitalMessageService.selectByExample(exampleHospital).get(0);
        emailEntityExt.setData("尊敬的" + userMessageEntity.getName()  + "用户，" + "您在" + hospitalMessageEntity.getName() + "购买的药品订单" +
                "被取消，原因:\n" + req.getMsg());
        sendEmailUtils.sendEmails(emailEntityExt);
        //删除订单
        Example exampleOrder = new Example(OrderEntity.class);
        Example.Criteria criteriaOrder = exampleOrder.createCriteria();
        criteriaOrder.andEqualTo("orderUuid",req.getOrderUuid());
        criteriaOrder.andEqualTo("userUuid",req.getUserUuid());

        OrderEntity orderEntity = orderService.selectByExample(exampleOrder).get(0);
        List<MedicalsExt> list = JSONObject.parseArray(orderEntity.getOrderContent(),MedicalsExt.class);
        List<String> medicalUuids = list.stream().map(s->s.getMedicalUuid()).collect(Collectors.toList());
        Example example = new Example(HospitalMedicalEntity.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("hospitalUuid",orderEntity.getHospitalUuid());
        criteria.andIn("medicalUuid",medicalUuids);
        Map<String,HospitalMedicalEntity> map = hospitalMedicalService.selectByExample(example).stream().collect(Collectors.toMap(s->s.getMedicalUuid(),s->s));
        list.forEach(item -> {
            Example example1 = new Example(HospitalMedicalEntity.class);
            Example.Criteria criteria1 = example1.createCriteria();
            criteria1.andEqualTo("hospitalUuid",orderEntity.getHospitalUuid());
            criteria1.andEqualTo("medicalUuid",item.getMedicalUuid());
            HospitalMedicalEntity hospitalMedicalEntity = map.get(item.getMedicalUuid());
            HospitalMedicalEntity change = new HospitalMedicalEntity();
            change.setReserveCount(hospitalMedicalEntity.getReserveCount() + item.getCount());
            hospitalMedicalService.updateByExampleSelective(change,example1);
        });
        orderService.deleteByExample(exampleOrder);
    }
}
